<?php
declare (strict_types=1);

namespace app\command;

use app\common\Common;
use app\cps\service\DebugLosService;
use app\model\DebugLogs;
use app\model\LaunchAccount;
use app\model\Link;
use app\model\PayRecord;
use app\model\ResponsibilityPerson;
use app\model\User;
use app\model\Videos;
use think\console\Command;
use think\console\Input;
use think\console\Output;
use think\facade\Cache;
use think\facade\Db;

class douYinRealTimeInvestData extends Command
{
    private $model;
    private $payRecordModel;
    private $userModel;
    private $videosModel;
    private $responsibilityPersonModel;
    private $launchAccountModel;

    protected function configure()
    {
        // 指令配置
        $this->setName('douyinrealtimeinvestdata')
            ->setDescription('the douyinrealtimeinvestdata command');
    }

    protected function initModel()
    {
        $this->model = new Link();
        $this->payRecordModel = new PayRecord();
        $this->userModel = new User();
        $this->videosModel = new Videos();
        $this->responsibilityPersonModel = new ResponsibilityPerson();
        $this->launchAccountModel = new launchAccount();
    }

    /**
     * 命令行的执行。
     * @param Input $input
     * @param Output $output
     * @return int|void|null
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    protected function execute(Input $input, Output $output)
    {
        // 实例化模型。命令行没法使用注入方式。
        //$this->initModel();
        // 执行数据的获取.
        //$rs = $this->collectData();
        // 返回结果
        /*if ($rs) { // 如果有错误。
            $error = $rs['message'] ?? '';
            $debugLogs = new DebugLogs();
            $debugLogsService = new DebugLosService($debugLogs);
            // 数据
            $insert_data = ['link_id' => 0, 'order_id' => 0, 'db_result' => $error, 'debug_scene' => '抖音获取投放数据'];
            // 记录下
            $debugLogsService->save($insert_data, 'invest_data_collection');
        }*/
    }

    /**
     * 获取数据
     * @return array|string[]
     */
    protected function collectData()
    {
        try {

            ini_set('memory_limit', '-1');

            $where[] = ['media_id', '=', 1];

            $redis = Cache::store('redis')->handler();
            $redis->select(5);

            // 缓存有销售时间.
            $cache_time = 24 * 60 * 60;

            $key1 = config('redis_key.real_time_investment_create_time') . date('Ymd');
            $key2 = config('redis_key.real_time_investment_total_click_num') . date('Ymd');
            $key3 = config('redis_key.real_time_investment_total_new_user') . date('Ymd');
            $key4 = config('redis_key.real_time_investment_link_user_register_num');

            // 分销商链接不查询
            $distributorResponsibilityPerson = $this->responsibilityPersonModel->getDataByWhere(['pid' => Db::raw('IS NOT NULL')], 'id');
            $distributorResponsibilityPersonIds = array_column($distributorResponsibilityPerson, 'id');

            // 调试用
            //$linkData = $this->model->getDataByWhere([['id','=','4402'],['media_id', '=', 1], ['link_switch', '=', 1], ['responsibility_person_id', 'not in', $distributorResponsibilityPersonIds]], 'id, video_id, video_detail_id, advertiser_id, responsibility_person_id, version, project_id, rebate, echo_rate, subject_id');
            $linkData = $this->model->getDataByWhere([['media_id', '=', 1], ['link_switch', '=', 1], ['responsibility_person_id', 'not in', $distributorResponsibilityPersonIds]], 'id, video_id, video_detail_id, advertiser_id, responsibility_person_id, version, project_id, rebate, echo_rate, subject_id');

            $appId = config('tiktok.huge_amount.app_id');
            $secret = config('tiktok.huge_amount.secret');
            $accessToken = Common::getHugeAmountAccessToken($appId, $secret);
            $appId1 = config('tiktok.huge_amount_yaodao.app_id');
            $secret1 = config('tiktok.huge_amount_yaodao.secret');
            $accessToken1 = Common::getHugeAmountAccessToken($appId1, $secret1);

            $appId24 = config('tiktok.huge_amount_xingcan.app_id');
            $secret24 = config('tiktok.huge_amount_xingcan.secret');
            $accessToken24 = Common::getHugeAmountAccessToken($appId24, $secret24);

            // $appId5 = config('tiktok.huge_amount_sixseals_erfen.app_id');
            // $secret5 = config('tiktok.huge_amount_sixseals_erfen.secret');
            // $accessToken5 = Common::getHugeAmountAccessToken($appId5, $secret5);

            $hearder['json'] = 1;

            $startDate = date('Y-m-d');
            $endDate = date('Y-m-d');

            $data = $accountIds = $responsibilityPersonIds = [];
            // $url = 'https://ad.oceanengine.com/open_api/2/report/campaign/get/';
            $url = 'https://api.oceanengine.com/open_api/v3.0/project/list/';
            $url2 = 'https://api.oceanengine.com/open_api/v3.0/report/custom/get/';

            $totalClickNum = $totalNewUserCount = 0;

            foreach ($linkData as $value) {

                //sleep(5); // 不然太忙。

                if (empty($value['advertiser_id'])) {
                    continue;
                }

                if ($value['subject_id'] == 8) {
                    $hearder['headers'] = ['Access-Token:' . $accessToken1];
                } elseif ($value['subject_id'] == 24) {
                    $hearder['headers'] = ['Access-Token:' . $accessToken24];
                } else {
                    $hearder['headers'] = ['Access-Token:' . $accessToken];
                }

                // 获取成本
                $getProjectBody = [
                    'advertiser_id' => intval($value['advertiser_id']),
                    'fields' => ['project_id'],
                    'page_size' => 100
                ];

                $getProjectRequestData = [];
                foreach ($getProjectBody as $k1 => $val1) {
                    $getProjectRequestData[$k1] = is_string($val1) ? $val1 : json_encode($val1);
                }

                $getProjectResult = Common::_curl($url, $getProjectRequestData, 'GET', $hearder);
                $getProjectResult = is_string($getProjectResult) ? json_decode($getProjectResult, true) : ['code' => 1, 'message' => '巨量返回格式错误1'];

                if ($getProjectResult['code'] != 0) {
					// by huangxiaoshan update 2023-07-18
					//continue;
                    return ['message' => '接口1：' . $getProjectResult['message'] . '；link_id：' . $value['id']];
                }

                if (empty($getProjectResult['data']['list'])) {
                    // $responsibilityPersonResult = $this->responsibilityPersonModel->getInfoById($value['responsibility_person_id'], 'name');
                    // return ['message' => '链接ID：'.$value['id'].'（所属投放：'.$responsibilityPersonResult['name'].'） 没有在投放的项目，请关闭投放开关'];
                    continue;
                }

                $string = '';
                foreach ($getProjectResult['data']['list'] as $val2) {
                    $string .= $val2['project_id'] . ',';
                }
                $projectIdString = substr($string, 0, -1);
                $projectId = explode(',', $projectIdString);
                if (!empty($projectId)) $this->model->edit(['id' => $value['id'], 'project_id' => $projectIdString]);

                $body = [
                    'dimensions' => ['stat_time_day', 'cdp_project_name'],
                    'advertiser_id' => $value['advertiser_id'], // 广告账户id
                    'start_time' => $startDate,
                    'end_time' => $endDate,
                    'metrics' => ['stat_cost'],
                    'order_by' => [
                        [
                            'field' => 'stat_time_day',
                            'type' => 'DESC'
                        ]
                    ],
                    'filters' => [
                        [
                            'field' => 'cdp_project_id',
                            'type' => 3,
                            'operator' => 1,
                            'values' => $projectId // 项目id
                        ]
                    ]
                ];

                $requestData = [];
                foreach ($body as $k => $val) {
                    $requestData[$k] = is_string($val) ? $val : json_encode($val);
                }

                $result = Common::_curl($url2, $requestData, 'GET', $hearder);
                $result = is_string($result) ? json_decode($result, true) : ['code' => 1, 'message' => '抓取异常'];

                if (!$result['code']) { // 状态码是0是成功的。

                    $value['cost'] = 0;
                    // if (!empty($result['data']['rows'])) {
                    //     foreach ($result['data']['rows'] as $key => $item) {
                    //         $value['cost'] += $item['metrics']['stat_cost'];
                    //     }
                    // }
                    if (!empty($result['data']['total_metrics'])) {
                        $value['cost'] = $result['data']['total_metrics']['stat_cost'];
                    }

                    $data[] = $value;
                } else {
					// by huangxiaoshan update 2023-07-18
					//continue;
                    return ['message' => '接口2：' . $result['message'] . '；link_id：' . $value['id']];
                }

                $accountIds[] = trim($value['advertiser_id']);
                $responsibilityPersonIds[] = $value['responsibility_person_id'];
            }

            if ($data) {
                // 短剧
                $videoIds = array_column($data, 'video_id');
                $videoData = $this->videosModel->getDataByIds($videoIds, 'id, name');
                $videos = array_column($videoData, 'name', 'id');

                $ids = array_column($data, 'id');
                $userWhere = [
                    ['link_id', 'in', $ids],
                    ['activation_time', 'between', [date('Y-m-d') . ' 00:00:00', date('Y-m-d') . ' 23:59:59']]
                ];
                $userInfo = $this->userModel->getBatchDataByWhere($userWhere, 'id, link_id');
                $payData = $this->payRecordModel->getInfo(['link_id' => $ids, 'status' => 1, 'consume_date' => date('Ymd')], 'link_id, uid, total_fee, activation_time');

                $newUserPayData = $rechargeNumber = $newUserNum = [];

                // by huangxiaoshan update 为了兼容CPS那边的取数据的方法。
                $redisUserLinkRegisterData = [];
                // end.

                if ($userInfo) {
                    $newUids = array_column($userInfo, 'id');
                    $totalNewUserCount = count($newUids);
                    // by huangxiaoshan update 为了兼容CPS那边的取数据的方法。
                    foreach ($userInfo as $key => $value) {
                        $redisUserLinkRegisterData[$value['link_id']][] = $value['id'];
                    }
                    // end
                    // 当天这个链接上的用户数据
                    $links = array_column($userInfo, 'link_id');
                    $userData = array_count_values($links);
                }

                // 当天新用户充值（当期充值）
                $startTime = strtotime(date('Y-m-d'));
                $endTime = strtotime(date('Y-m-d')) + 86400;
                foreach ($payData as $key => $value) {
                    if (strtotime($value['activation_time']) >= $startTime && $endTime > strtotime($value['activation_time'])) {
                        $newUserPayData[$value['link_id']][] = $value['total_fee'];
                        $newUserNum[$value['link_id']][] = $value['uid'];
                    }

                    $rechargeNumber[$value['link_id']][] = $value['uid'];
                }

                // 获取返点数据
                $launchAccountData = $this->launchAccountModel->getDataByWhere(['account_id' => $accountIds], 'account_id, rebate');
                $launchAccount = array_column($launchAccountData, 'rebate', 'account_id');

                // 获取负责人数据
                $responsibilityPersonData = $this->responsibilityPersonModel->getDataByWhere(['id' => $responsibilityPersonIds], 'id, name');
                $responsibilityPerson = array_column($responsibilityPersonData, 'name', 'id');

                foreach ($data as $key => $item) {
                    $data[$key]['video_name'] = $videos[$item['video_id']];

                    $currentRecharge = empty($newUserPayData[$item['id']]) ? 0 : array_sum($newUserPayData[$item['id']]);
                    $data[$key]['current_recharge'] = round($currentRecharge, 2); // 当期充值

                    // by huangxiaoshan 2023-07-12 当期充值95折扣
                    $tmp_discount_data = bcmul((string)$currentRecharge, '0.95', 3); // 当前充值的95折扣
                    $data[$key]['current_recharge_discount'] = round($tmp_discount_data, 2);
                    // end

                    $data[$key]['current_recovery'] = $item['cost'] == 0 ? 0 : round($currentRecharge / $item['cost'] * 100, 2) . '%'; // 当期回收

                    $conversionNumber = empty($rechargeNumber[$item['id']]) ? 0 : count(array_unique($rechargeNumber[$item['id']])); // 充值人数
                    $data[$key]['conversion_number'] = $conversionNumber;
                    $data[$key]['conversion_cost'] = $conversionNumber == 0 ? 0 : round($item['cost'] / $conversionNumber, 2); // 转化成本

                    $newRechargeNumber = empty($newUserPayData[$item['id']]) ? 0 : count($newUserPayData[$item['id']]); // 新充笔数
                    $newUserNumber = empty($newUserNum[$item['id']]) ? 0 : count(array_unique($newUserNum[$item['id']])); // 新充人数
                    $data[$key]['new_recharge_number'] = $newRechargeNumber;
                    $data[$key]['new_user_number'] = $newUserNumber;

                    // 转化率
                    $data[$key]['conversion_rate'] = !empty($userData[$item['id']]) ? round($newUserNumber / $userData[$item['id']] * 100, 2) . '%' : '0%';
                    $totalClickNum += empty($userData[$item['id']]) ? 0 : $userData[$item['id']];

                    $data[$key]['fans_cost'] = !empty($userData[$item['id']]) ? round($item['cost'] / $userData[$item['id']]) : 0; // 粉丝成本
                    // $totalRecharge = empty($payResult[$item['id']]) ? 0 : array_sum($payResult[$item['id']]); // 当天累计充值
                    $data[$key]['total_recharge'] = $currentRecharge; // 当天累计充值暂时等于当期充值

                    $data[$key]['per_capita_contribution'] = $newUserNumber == 0 ? 0 : round($currentRecharge / $newUserNumber, 2); // 人均贡献

                    // by update huangxiaoshan 2023-07-13(给CPS那边用的。)
                    $userLinkRegisterNum = empty($redisUserLinkRegisterData[$item['id']]) ? 0 : count($redisUserLinkRegisterData[$item['id']]);
                    $redis->set($key4 . $item['id'], $userLinkRegisterNum, 30 * 60);
                    // end

                    $data[$key]['media_id'] = 1; // 抖音

                    // 实际花费
                    $actualCost = 0;
                    if (!empty($item['rebate'])) {
                        $actualCost = round($item['cost'] / ($item['rebate'] / 100 + 1), 2);
                    } else if (!empty($launchAccount[$item['advertiser_id']])) {
                        $actualCost = round($item['cost'] / ($launchAccount[$item['advertiser_id']] / 100 + 1), 2);
                    }
                    unset($data[$key]['rebate']);
                    // $actualCost = !empty($launchAccount[$item['advertiser_id']]) ? round($item['cost'] / ($launchAccount[$item['advertiser_id']] / 100 + 1), 2) : 0;
                    $data[$key]['actual_recovery'] = $actualCost == 0 ? 0 : round($currentRecharge / $actualCost * 100, 2) . '%'; // 实际回收
                    $data[$key]['actual_cost'] = $tmp_actual_cost = round($actualCost, 2);

                    // by huangxiaoshan 2023-07-12 新增95折净利润
                    $profit = bcsub((string)$tmp_discount_data, (string)$tmp_actual_cost, 2);
                    $data[$key]['current_recharge_profit'] = $profit;
                    // end

                    // 负责人数据
                    $data[$key]['responsibility_person_name'] = $responsibilityPerson[$item['responsibility_person_id']];

                    $data[$key]['revenue'] = round($currentRecharge - $actualCost, 2); // 营收情况
                    unset($data[$key]['subject_id']);

                    // by huangxiaoshan 2023-07-14 新增订单人数
                    $order_count = empty($newUserPayData[$item['id']]) ? 0 : count($newUserPayData[$item['id']]);
                    $data[$key]['order_count'] = $order_count;
                    $data[$key]['avg_person_order'] = 0;
                    if ($order_count && $newUserNumber) {
                        $data[$key]['avg_person_order'] = round(bcdiv((string)$order_count, (string)$newUserNumber, 3),2);
                    }
                    // end
                }
            }

            Db::name('real_time_data_cache')->where(['media_id' => 1])->delete(true);

            Db::name('real_time_data_cache')->insertAll($data);

            // 产生数据生成时间标记.
            $redis->set($key1, time(), $cache_time); // 数据产生的时间
            $redis->set($key2, $totalClickNum, $cache_time);
            $redis->set($key3, $totalNewUserCount, $cache_time);

            return [];

        } catch (\Exception $e) {
            $error = "抖音投放账号数据实时采集错误：" . $e->getLine() . "|" . $e->getMessage();
            return ['message' => $error];
        }
    }
}
